ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
Decision.c
Go to the documentation of this file.
00001 
00016 #include "derivative.h"
00017 #include "Compile_Options.h"
00018 #include "Decision.h"
00019 #include "SM.h"
00020 #include "SBC_AL.h"
00021 #include "HAL.h"
00022 #include "MailScheduler.h"
00023 #include "Application_Globals.h"
00024 #include "SIU.h"
00025 /*
00026  ******************************************************************************
00027  * Constants
00028  ******************************************************************************
00029  */
00031 const uint16_t cau16PreDecisionValidStates[] =
00032 {
00033   SM_STATE_ERROR, SM_APPLICATION_START };
00034 /*
00035  ******************************************************************************
00036  * Globals
00037  ******************************************************************************
00038  */
00039 /*
00040  ******************************************************************************
00041  * u32fnStateDecision
00042  ******************************************************************************
00043  */
00044 uint32_t u32fnStateDecision(void)
00045 {
00046   uint32_t u32Status;
00047   
00048   
00049   /* Verify that we can execute - Previous state ended correctly */
00050   u32Status
00051       = u32fnSMValidateCurrentState((uint16_t*)cau16PreDecisionValidStates,
00052                                     N_ELEMENTS(cau16PreDecisionValidStates));
00053   if(CLEAR == u32Status)
00054   {
00055     /* Here comes the real contents of the state */
00056     LOCK_STATE_EXECUTION();
00057     
00058     /* Run the algorithm */
00059     u32Status = u32fnDecisionMath(gu16ActivePSI5Channels, 
00060                                   (uint16_t*)&gau16RawAccels[SM_PSI5_GLOBAL_INDEX],
00061                                   (uint16_t*)&gu16CrashedSatellites);
00062     if(CLEAR == u32Status)
00063     {
00064       /* Run  the Safing */
00065       u32Status = u32fnDecisionSafing(gu16CrashedSatellites,
00066                                 (uint16_t*)&gau16RawAccels[SM_CA_GLOBAL_INDEX],
00067                                 (uint16_t*)&gu16ConfirmedSatellites);
00068       
00069       /* Result from operation above will flag confirmed satellites only;    */
00070       /* meaning that if the error flag is set, it is due to an unconfirmed  */
00071       /* satellite. Therefore, we must treat this error accordingly, but we  */
00072       /* shall also decide which squibs are going to be triggered. Therefore */
00073       /* the next step does not require an empty u32Status, but it will      */
00074       /* remember the previous one and report it.                            */
00075       u32Status |= u32fnDecisionSelection(gu16ConfirmedSatellites,
00076                                           gu16ActiveSquibChannels,
00077                                           (uint16_t*)&gu16SquibsToFire);
00078     }
00079     else
00080     {
00081       /* Leave with error code */
00082     }
00083     /* Unlock the state */
00084     UNLOCK_STATE_EXECUTION();
00085   }
00086   else
00087   {
00088     /* Leave */
00089   }
00090 
00091   /* Set the next state */
00092   if(CLEAR == u32Status)
00093   {
00094     vfnSMWriteNextState(SM_STATE_DEPLOYMENT);
00095   }
00096   else
00097   {
00098     vfnSMWriteNextState(SM_STATE_ERROR);
00099   }
00100   return (u32Status);
00101 }
00102 /*
00103  ******************************************************************************
00104  * u32fnDecisionMath
00105  ******************************************************************************
00106  */
00107 static uint32_t u32fnDecisionMath(const uint16_t cu16PSI5Channels, 
00108                                   const uint16_t* pu16Acceleration, 
00109                                   uint16_t* pu16SatelliteSensedCrash)
00110 {
00111   uint32_t u32Status;
00112   uint8_t u8Index;
00113   uint16_t u16ChannelMask;
00114   
00115   u32Status = CLEAR;
00116   u8Index = CLEAR;
00117   
00118   /* Below is a sample application where satellite sensors are compared   */
00119   /* against a threshold; if the threshold is passed, we assume there has */
00120   /* been an impact detected by the sensor. Real world application should */
00121   /* replace this threshold detection since it is not tested in any kind  */
00122   /* of environment other than a lab with an evaluation board and is not  */
00123   /* representative of a complete solution.                               */
00124   *pu16SatelliteSensedCrash = CLEAR;
00125   for(u16ChannelMask = BIT0; u16ChannelMask < BIT12; u16ChannelMask <<= 1u)
00126   {
00127     if(u16ChannelMask & cu16PSI5Channels)
00128     {
00129       /* If the channel is active, check the acceleration vs. the threshold */
00130       *pu16SatelliteSensedCrash |=  
00131           (*(pu16Acceleration + u8Index) > cau16PSI5CrashThresholds[u8Index]) 
00132            << u8Index;
00133     }
00134     else
00135     {
00136       /* Not going to perform a test against this */
00137     }
00138     u8Index++;
00139   }
00140   return(u32Status);
00141 }
00142 /*
00143  ******************************************************************************
00144  * u32fnDecisionSafing
00145  ******************************************************************************
00146  */
00147 static uint32_t u32fnDecisionSafing(const uint16_t cu16CrashedSatellites, 
00148                                     const uint16_t* pu16CAAccel,
00149                                     uint16_t* pu16ConfirmedSatellites)
00150 {
00151   uint32_t u32Status;
00152   uint8_t  au8CAShock[2u];
00153   uint8_t u8Index;
00154   uint16_t u16ChannelMask;
00155   
00156   /* Init variables */
00157   u8Index = CLEAR;
00158   *pu16ConfirmedSatellites = CLEAR;
00159   u32Status = CLEAR;
00160   
00161   /* We will now consult our central accelerometer with regards to the crash */
00162   /* A "1" will be set if there has been a crash, "0" otherwise.             */
00163   au8CAShock[CA_CRASH_X] = (*pu16CAAccel > cau16CACrashThresholds[CA_CRASH_X]);
00164   au8CAShock[CA_CRASH_Y] = (*(pu16CAAccel + 1u) > 
00165                                cau16CACrashThresholds[CA_CRASH_Y]);
00166   
00167   /* Next, we will go through all satellites */
00168   for(u16ChannelMask = BIT0; u16ChannelMask < BIT12; u16ChannelMask <<= 1u)
00169   {
00170     if(cu16CrashedSatellites & u16ChannelMask)
00171     {
00172       /* This satellite has detected a crash condition. Check it against */
00173       /* it's safing axis which is correlated through a special table    */
00174       if(TRUE == au8CAShock[cau8SatelliteDetectionDirection[u8Index]])
00175       {
00176         /* CA has detected a shock in the pertinent direction */
00177         /* we agree with it, therefore we can continue checking DIS_ALP and DIS_AHP*/
00178         if((CLEAR == u8fnReadPin(PIN_DIS_ALP)) && (CLEAR == u8fnReadPin(PIN_DIS_AHP)))
00179         {
00180           /* Add to the list of confirmed satellites */
00181           *pu16ConfirmedSatellites |= u16ChannelMask;
00182         }/* end if safing is confirmed */
00183         else
00184         {
00185           /* Safing has not been confirmed. We need to flag this in the */
00186           /* status word                                                */
00187           u32Status |= DECISION_ERROR_SAFING_PIN;
00188         } /* end else (safing is not confirmed) */
00189       } /* end if CA confirms acceleration axis */
00190       else
00191       {
00192         /* The accelerometer did not agree with the satellite. */
00193         /* This is not an error, just a working condition. */
00194         /* We will not flag it */
00195         /* u32Status |= CLEAR; */
00196       } /* end else (CA does not confirm acceleration axis) */
00197     } /* end if satellite has been detected as crashed */
00198     else
00199     {
00200       /* This satellite has not been crashed */
00201     }
00202     u8Index++;
00203   }
00204   return(u32Status);
00205 }
00206 /*
00207  ******************************************************************************
00208  * u32fnDecisionSelection
00209  ******************************************************************************
00210  */
00211 static uint32_t u32fnDecisionSelection(const uint16_t cu16ConfirmedSatellites,
00212                                        const uint16_t cu16ActiveSquibs,
00213                                        uint16_t* pu16SquibsToFire)
00214 {
00215   uint32_t u32Status;
00216   uint8_t u8Index1;
00217   uint8_t u8Index2;
00218   uint16_t u16ChannelMask;
00219   
00220   u32Status = CLEAR;
00221   
00222   /* Index1 will tell us which satellite we're referring to */
00223   u8Index1 = CLEAR;
00224   
00225   /* Forget any previous firing values */
00226   *pu16SquibsToFire = CLEAR;
00227   
00228   for(u16ChannelMask = BIT0; u16ChannelMask < BIT12; u16ChannelMask <<= 1u)
00229   {
00230     if(u16ChannelMask & cu16ConfirmedSatellites)
00231     {
00232       /* If this is a confirmed satellite, we need to fire all squibs    */
00233       /* related to it Index2 keeps record of where in the relationship  */
00234       /* table between satellites and squibs we are.                     */
00235       for(u8Index2 = CLEAR; u8Index2 < cu8SizeOfSatToSquibs; u8Index2 += 2u)
00236       {
00237         /* We will search the whole table */
00238         if(cau8SatToSquibs[u8Index2] == u8Index1)
00239         {
00240           /* And if there's a match, we will verify that this is an active */
00241           /* squib - we never want to enable an inactive squib.            */
00242           if(cu16ActiveSquibs & (BIT0 << cau8SatToSquibs[(u8Index2 + 1u)]))
00243           {
00244             /* If this is the satellite in question, enable the squib if */
00245             *pu16SquibsToFire |= (BIT0 << cau8SatToSquibs[(u8Index2 + 1u)]);
00246           }
00247           else
00248           {
00249             /* This is an inactive squib, we can't do anything about it */
00250           }
00251         }
00252         else
00253         {
00254           /* There's nothing to do */
00255         } 
00256       } /* End for */ 
00257     } /* end if squib is active */
00258     else
00259     {
00260       /* Don't fire anything */
00261     } /* end else (squib is not active) */
00262     u8Index1++;
00263   }/* end for */
00264   
00265   return(u32Status);
00266 }
00267 /*
00268  ******************************************************************************
00269  *
00270  *  End of file.
00271  *
00272  ******************************************************************************
00273  */